package ConcurrentProgramming;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 加入一个线程   join方法
 * 1. 作用
 *      把指定的线程加入到当前线程，可以将两个交替执行的线程合并为顺序执行。
 *      比如在线程B中调用了线程A的Join()方法，直到线程A执行完毕后，才会继续执行线程B。
 *      通俗来说：如果在线程B的执行过程中调用了A的join方法，则B线程必须等待A线程执行完毕
 *      之后才能继续执行
 *
 *
 * 2. 原理   join方法是如何阻塞线程的，又是如何唤醒线程的?
 *      wait方法是使持有锁的线程进入等待队列，所以主线程会阻塞。
 *      唤醒进程的方法位于jvm中，在线程（调用join方法的线程）结束后主线程被调用。
 *
 * 3. 方法的相关参数
 */
class Girl extends Thread{
    @Override
    public void run() {
        System.out.println("Girl开始打饭  打饭时间为2s");
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"Girl打饭完毕");
    }
}

class Boy extends Thread{
    private Girl girl;

    public Boy(Girl girl) {
        this.girl = girl;
    }
    @Override
    public void run() {
        System.out.println("Boy开始打饭 打饭时间为2s");
        try {
            girl.start();
            girl.join();
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "boy打饭完毕");
    }
}

class TestJoin extends Thread {
    static int count = 0;
    @Override
    public void run() {
        System.out.println(currentThread().getName());
        count = 10;
    }
}


public class AddAThread {
    public static void main(String[] args) throws InterruptedException {
        testJoin2();
    }

    /**
     * 测试join函数的效果
     * boy开始打饭
     * Boy开始打饭 打饭时间为2s
     * Girl开始打饭  打饭时间为2s
     * Thread-0Girl打饭完毕
     * Thread-1boy打饭完毕
     *
     * 直到girl线程执行完毕之后boy线程才开始执行到完毕
     */
    public static void testJoin() {
        System.out.println("boy开始打饭"); // 这是主线程执行的
        Girl girl = new Girl();
        Boy boy = new Boy(girl);
        boy.start();
    }

    /**
     * 结果
     *  Thread-0
     *  10
     * 解释：
     *  由于testJoin线程调用了join方法
     *  testJoin先执行，则在run方法中修改了静态变量count的值为10，而主线程被挂起了，必须等待子线程执行完毕
     *  如果将join注释掉，则此时先执行主线程，所以此时打印的是原有的count=0，还没有被子线程修改，所以打印的是0
     * @throws InterruptedException
     */
    public static void testJoin2() throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        testJoin.start();
        testJoin.join(5000);
        System.out.println(TestJoin.count+Thread.currentThread().getName());
    }
}


